#include "../include/head.h"
#include "../include/func.h"

#define BUFFER_SIZE 4096

int encrypt_password(const char *password, const char *salt, char *encrypted_password) {
    char combined[BUFFER_SIZE];
    unsigned char hash[SHA256_DIGEST_LENGTH];

    // 将盐值和密码连接在一起,将两个字符串 password 和 salt 拼接到 combined 中，且是安全地格式化写入，不会造成缓冲区溢出
    snprintf(combined, sizeof(combined), "%s%s", password, salt);

    // 使用 SHA-256 hash函数进行加密
    SHA256((unsigned char *)combined, strlen(combined), hash);

    // 把哈希值转换为十六进制字符串
    for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
        snprintf(encrypted_password + (i * 2), 3, "%02x", hash[i]);
    }
    encrypted_password[SHA256_DIGEST_LENGTH * 2] = '\0'; // 确保字符串终止符
    return 0;
}

int register_client(int sockfd) {
    char response[BUFFER_SIZE];
    char username[BUFFER_SIZE];
    char password[BUFFER_SIZE];
    char salt[BUFFER_SIZE];
    char encrypted_password[BUFFER_SIZE];
    int length;
    CmdType cmdType;    // 声明枚举类型

    printf("\033[1;97m您好，请输入新的用户名：\033[0m");
    fgets(username, sizeof(username), stdin);
    username[strlen(username) - 1] = '\0';
    // 1.待发送消息的长度
    length = strlen(username);
    send(sockfd, &length, sizeof(length), 0);
    // 2.待发送消息的类型
    cmdType = CMD_TYPE_REGISTER_USERNAME;
    send(sockfd, &cmdType, sizeof(cmdType), 0);
    // 3.发送用户的信息，填充结构体成员
    User_t user = {
        .id = 1,
        .salt = "salt",
        .cryptpasswd = "cryptpasswd",
        .pwd = "pwd"
    };
    strcpy(user.userName, username);
    printf("%s\n", user.userName);
    send(sockfd, &user, sizeof(user), 0);

    // 等待服务器的响应
    int ret = recv(sockfd, response, sizeof(response), 0);

    // 检查盐值
    // string strstr （string search substring）
    // char *strstr(const char *haystack, const char *needle);
    // 在字符串 haystack 中查找第一次出现的子字符串 needle。
    // 返回指向 needle 首次出现位置的指针。
    // 如果没找到，返回 NULL。
    if (strstr(response, "SALT")) {
        sscanf(response, "SALT:%s", salt);
        // 提示用户输入密码
        printf("\033[1;97m您好，请输入密码：\033[0m");
        fgets(password, sizeof(password), stdin);
        password[strlen(password) - 1] = '\0';
        // 对盐值进行加密
        encrypt_password(password, salt, encrypted_password);

        // 1.发送消息长度
        length = strlen(encrypted_password);
        send(sockfd, &length, sizeof(length), 0);
        // 2.发送消息类型
        cmdType = CMD_TYPE_REGISTER_ENCRYTPTEDCODE;
        send(sockfd, &cmdType, sizeof(cmdType), 0);
        // 3.发送用户消息
        memset(&user, 0, sizeof(user));
        user = (User_t){
            .userName = username,
            .salt = salt,
            .cryptpasswd = encrypted_password,
            .pwd = username
        };
        send(sockfd, &user, sizeof(user), 0);
        // 接受服务器的注册响应
        int ret = recv(sockfd, response, sizeof(response), 0);
        response[ret] = '\0';
        if (strstr(response, "MSG_TYPE_REGISTEROK")) {
            printf("\033[1;97m注册成功！！！\033[0m");
        } else {
            printf("注册失败，错误代码：%s\n", response);
        }
    } else {
        printf("\033[1;5;97;41m用户名已存在，注册失败，请重试。\033[0m\n");
    }
    return 0;
}